#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
事件处理器
负责所有UI事件的处理逻辑
"""

import os
import tkinter as tk
from tkinter import messagebox


class EventHandlers:
    """事件处理器混入类"""
    
    def on_file_double_click(self, event, tree):
        """处理文件双击事件"""
        self.add_log(f"[DEBUG] 双击事件触发，位置: ({event.x}, {event.y})", 'info')
        
        try:
            column = tree.identify_column(event.x)
            self.add_log(f"[DEBUG] 点击列: {column}", 'info')
            
            if column == '#1':  
                self.add_log(f"[DEBUG] 点击的是复选框列，跳过", 'info')
                return
                
            item = tree.selection()[0] if tree.selection() else None
            if not item:
                self.add_log(f"[DEBUG] 没有选中的项目", 'warning')
                return
                
            item_data = tree.item(item)
            self.add_log(f"[DEBUG] 项目数据: {item_data}", 'info')
            
            file_path = item_data.get('tags', [''])[0] if item_data.get('tags') else ''
            
            if not file_path:
                file_path = item_data['text']  
            
            # 标准化路径格式
            if file_path:
                file_path = os.path.normpath(file_path)
            
            self.add_log(f"[DEBUG] 双击项目: {item_data['text']}, 解析路径: {file_path}", 'info')
            
            if file_path.startswith('重复组') or file_path in ['duplicate_group', 'project_type_group', 'category_group']:
                self.add_log(f"[INFO] 跳过分组标题行", 'info')
                return
                
            if os.path.exists(file_path):
                self.add_log(f"[INFO] 文件存在，正在打开位置: {file_path}", 'info')
                
                # 添加更详细的路径信息
                if os.path.isdir(file_path):
                    self.add_log(f"[DEBUG] 这是一个目录", 'info')
                elif os.path.isfile(file_path):
                    self.add_log(f"[DEBUG] 这是一个文件", 'info')
                
                if self.core.open_file_location(file_path, self.add_log):
                    self.add_log(f"-> ✅ 已成功打开文件位置", 'success')
                else:
                    self.add_log(f"[ERROR] ❌ 无法打开文件位置，请查看上面的详细错误信息", 'error')
            else:
                self.add_log(f"[ERROR] 文件不存在: {file_path}", 'error')
        except Exception as e:
            self.add_log(f"[ERROR] 双击处理出错: {str(e)}", 'error')
    
    def on_tree_click(self, event, tree):
        """处理树形控件点击事件"""
        item = tree.identify_row(event.y)
        if not item:
            return
            
        column = tree.identify_column(event.x)
        if column == '#1':  
            self.toggle_item_check(tree, item)

    def toggle_item_check(self, tree, item):
        """切换项目的复选框状态"""
        tree_name = self.get_tree_name(tree)
        if not tree_name:
            return
        
        if tree_name not in self.checked_items:
            self.checked_items[tree_name] = {}
        
        # 获取项目信息
        item_data = tree.item(item)
        tags = item_data.get('tags', [])
        
        current_state = self.checked_items[tree_name].get(item, False)
        new_state = not current_state
        self.checked_items[tree_name][item] = new_state
        
        check_symbol = '☑' if new_state else '☐'
        tree.set(item, 'check', check_symbol)
        
        # 检查是否是特殊节点（分类或项目类型）
        if tags and len(tags) > 0:
            tag_type = tags[0]
            if tag_type == 'category_group':
                # 分类节点：批量切换该分类下的所有子项目
                self.toggle_category_children(tree, item, new_state, tree_name)
                category_name = item_data['text']
                action = "选中" if new_state else "取消选中"
                child_count = len(tree.get_children(item))
                self.add_log(f"[INFO] 📋 {action}分类 {category_name} 下的 {child_count} 个项目", 'info')
                return
            elif tag_type == 'project_type_group':
                # 项目类型节点：批量切换该类型下的所有项目
                self.toggle_project_type_children(tree, item, new_state, tree_name)
                project_type = item_data['text']
                action = "选中" if new_state else "取消选中"
                child_count = self.count_all_descendants(tree, item)
                self.add_log(f"[INFO] 🚀 {action}项目类型 {project_type} 下的所有 {child_count} 个项目", 'info')
                return
            elif tag_type == 'duplicate_group':
                # 重复文件组：批量切换该组下的所有重复文件
                self.toggle_children_check(tree, item, new_state, tree_name)
                group_name = item_data['text']
                action = "选中" if new_state else "取消选中"
                child_count = len(tree.get_children(item))
                self.add_log(f"[INFO] 📁 {action}重复组 {group_name} 下的 {child_count} 个文件", 'info')
                return
        
        # 普通项目的切换逻辑
        self.update_parent_check(tree, item, tree_name)
        self.toggle_children_check(tree, item, new_state, tree_name)

    def toggle_children_check(self, tree, parent_item, state, tree_name):
        """递归切换子项目的复选框状态"""
        children = tree.get_children(parent_item)
        for child in children:
            self.checked_items[tree_name][child] = state
            check_symbol = '☑' if state else '☐'
            tree.set(child, 'check', check_symbol)
            
            child_children = tree.get_children(child)
            if child_children:
                self.toggle_children_check(tree, child, state, tree_name)
    
    def toggle_category_children(self, tree, category_item, state, tree_name):
        """切换分类下所有子项目的复选框状态"""
        children = tree.get_children(category_item)
        for child in children:
            self.checked_items[tree_name][child] = state
            check_symbol = '☑' if state else '☐'
            tree.set(child, 'check', check_symbol)
            
            # 分类下的子项目通常是具体的文件夹，不需要再递归
            # 但为了保险起见，如果有子项目也一并处理
            grandchildren = tree.get_children(child)
            if grandchildren:
                self.toggle_children_check(tree, child, state, tree_name)
    
    def toggle_project_type_children(self, tree, project_type_item, state, tree_name):
        """切换项目类型下所有项目的复选框状态"""
        def toggle_recursive(parent_item):
            children = tree.get_children(parent_item)
            for child in children:
                self.checked_items[tree_name][child] = state
                check_symbol = '☑' if state else '☐'
                tree.set(child, 'check', check_symbol)
                
                # 递归处理子项目
                toggle_recursive(child)
        
        toggle_recursive(project_type_item)
    
    def count_all_descendants(self, tree, parent_item):
        """统计一个节点下所有子孙节点的数量"""
        count = 0
        
        def count_recursive(item):
            nonlocal count
            children = tree.get_children(item)
            count += len(children)
            for child in children:
                count_recursive(child)
        
        count_recursive(parent_item)
        return count

    def update_parent_check(self, tree, item, tree_name):
        """更新父项目的复选框状态"""
        parent = tree.parent(item)
        if not parent:
            return
        
        siblings = tree.get_children(parent)
        checked_siblings = [s for s in siblings if self.checked_items[tree_name].get(s, False)]
        
        if len(checked_siblings) == len(siblings):
            parent_state = True
        elif len(checked_siblings) == 0:
            parent_state = False
        else:
            parent_state = True  
        
        self.checked_items[tree_name][parent] = parent_state
        check_symbol = '☑' if parent_state else '☐'
        tree.set(parent, 'check', check_symbol)
        
        self.update_parent_check(tree, parent, tree_name)

    def get_tree_name(self, tree):
        """获取树控件的名称"""
        if tree == getattr(self, 'temp_tree', None):
            return 'temp'
        elif tree == getattr(self, 'dup_tree', None):
            return 'dup'
        elif tree == getattr(self, 'large_tree', None):
            return 'large'
        elif tree == getattr(self, 'dev_tree', None):
            return 'dev'
        return None

    def toggle_all_selection(self, tree):
        """全选/取消全选"""
        tree_name = self.get_tree_name(tree)
        if not tree_name:
            return
        
        if tree_name not in self.checked_items:
            self.checked_items[tree_name] = {}
        
        all_items = list(tree.get_children())
        
        def get_all_items_recursive(parent=''):
            items = list(tree.get_children(parent))
            all_items = items[:]
            for item in items:
                all_items.extend(get_all_items_recursive(item))
            return all_items
        
        all_items = get_all_items_recursive()
        
        any_checked = any(self.checked_items[tree_name].get(item, False) for item in all_items)
        new_state = not any_checked
        
        for item in all_items:
            self.checked_items[tree_name][item] = new_state
            check_symbol = '☑' if new_state else '☐'
            tree.set(item, 'check', check_symbol)
        
        header_symbol = '☑' if new_state else '☐'
        tree.heading('check', text=header_symbol)

    def on_tab_changed(self, event):
        """处理标签页切换事件"""
        current_tab = self.notebook.select()
        tab_text = self.notebook.tab(current_tab, 'text')
        
        tab_functions = {
            "临时文件": "temp",
            "重复文件": "dup", 
            "大文件": "large",
            "开发目录": "dev"
        }
        
        function_name = tab_functions.get(tab_text, "unknown")
        
        self.add_log(f"[INFO] 🔄 切换到功能: {tab_text} ({function_name})", 'info')
        
        if function_name in self.current_scan_data:
            data = self.current_scan_data[function_name]
            
            if function_name == "temp":
                count = len(data) if data else 0
                self.add_log(f"[INFO] 📊 当前显示: {count} 个临时文件", 'info')
                
            elif function_name == "dup":
                if isinstance(data, dict):
                    total_files = sum(len(files) for files in data.values())
                    groups = len(data)
                    self.add_log(f"[INFO] 📊 当前显示: {groups} 个重复组，共 {total_files} 个重复文件", 'info')
                
            elif function_name == "large":
                count = len(data) if data else 0
                if count > 0 and isinstance(data[0], tuple):
                    total_size = sum(size for _, size in data)
                    if total_size > 1024 * 1024 * 1024:  
                        size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
                    elif total_size > 1024 * 1024:  
                        size_str = f"{total_size / 1024 / 1024:.1f} MB"
                    else:
                        size_str = f"{total_size / 1024:.1f} KB"
                    self.add_log(f"[INFO] 📊 当前显示: {count} 个大文件，总计 {size_str}", 'info')
                else:
                    self.add_log(f"[INFO] 📊 当前显示: {count} 个大文件", 'info')
                
            elif function_name == "dev":
                count = len(data) if data else 0
                if count > 0:
                    total_size = 0
                    for dev_data in data:
                        if len(dev_data) >= 3:  # 确保有大小数据
                            total_size += dev_data[2]  # 第三个元素是大小
                    
                    if total_size > 0:
                        if total_size > 1024 * 1024 * 1024:  
                            size_str = f"{total_size / 1024 / 1024 / 1024:.1f} GB"
                        elif total_size > 1024 * 1024:  
                            size_str = f"{total_size / 1024 / 1024:.1f} MB"
                        else:
                            size_str = f"{total_size / 1024:.1f} KB"
                        self.add_log(f"[INFO] 📊 当前显示: {count} 个开发目录，总计 {size_str}，已按内容分类", 'info')
                    else:
                        self.add_log(f"[INFO] 📊 当前显示: {count} 个开发目录，已按内容分类", 'info')
        else:
            self.add_log(f"[INFO] ❌ {tab_text} 功能暂无数据，请先执行扫描", 'warning')

    def delete_selected(self):
        """删除选中文件（基于复选框选择）"""
        self.add_log("[DEBUG] 🖱️ 批量删除按钮被点击", 'info')
        
        try:
            current_tab_index = self.notebook.index("current")
            current_tab = [self.temp_frame, self.dup_frame, self.large_frame, self.dev_frame][current_tab_index]
            tab_names = ["临时文件", "重复文件", "大文件", "开发目录"]
            self.add_log(f"[DEBUG] 通过notebook获取标签页: index={current_tab_index}, 标签页='{tab_names[current_tab_index]}'", 'info')
        except Exception as e:
            self.add_log(f"[DEBUG] 通过notebook获取标签页失败: {e}", 'error')
            return
        
        if current_tab_index == 0:  
            tree = self.temp_tree
            data_key = 'temp'
            self.add_log(f"[DEBUG] ✅ 识别为临时文件标签页", 'info')
        elif current_tab_index == 1:  
            tree = self.dup_tree
            data_key = 'dup'
            self.add_log(f"[DEBUG] ✅ 识别为重复文件标签页", 'info')
        elif current_tab_index == 2:  
            tree = self.large_tree
            data_key = 'large'
            self.add_log(f"[DEBUG] ✅ 识别为大文件标签页", 'info')
        elif current_tab_index == 3:  
            tree = self.dev_tree
            data_key = 'dev'
            self.add_log(f"[DEBUG] ✅ 识别为开发目录标签页", 'info')
        else:
            self.add_log(f"[DEBUG] ❌ 未知的标签页索引: {current_tab_index}", 'error')
            return
        
        tree_name = self.get_tree_name(tree)
        self.add_log(f"[DEBUG] 树控件名称: {tree_name}", 'info')
        
        if not tree_name:
            self.add_log(f"[DEBUG] ❌ 无法获取树控件名称", 'error')
            messagebox.showwarning("警告", "无法识别当前列表！")
            return
            
        if tree_name not in self.checked_items:
            self.add_log(f"[DEBUG] ❌ 复选框状态未初始化，可用的树: {list(self.checked_items.keys())}", 'error')
            messagebox.showwarning("警告", "请先选择要删除的文件！")
            return
        
        self.add_log(f"[DEBUG] 所有复选框状态: {self.checked_items[tree_name]}", 'info')
        
        checked_items = [item_id for item_id, checked in self.checked_items[tree_name].items() if checked]
        self.add_log(f"[DEBUG] 选中的项目数量: {len(checked_items)}", 'info')
        
        if not checked_items:
            self.add_log(f"[DEBUG] ❌ 没有选中任何项目", 'warning')
            messagebox.showwarning("警告", "请先选择要删除的文件！")
            return
            
        self.add_log(f"[DEBUG] ✅ 找到 {len(checked_items)} 个选中项目，开始收集文件路径", 'info')
            
        files_to_delete = []
        
        def collect_files(item_id):
            """递归收集文件路径"""
            item_data = tree.item(item_id)
            tags = item_data.get('tags', [])
            
            if tags and len(tags) > 0:
                file_path = tags[0]
                
                if file_path in ['duplicate_group', 'project_type_group', 'category_group']:
                    for child in tree.get_children(item_id):
                        if self.checked_items[tree_name].get(child, False):
                            collect_files(child)
                    return
                
                if data_key == 'temp' and file_path in self.current_scan_data.get('temp', []):
                    files_to_delete.append(file_path)
                elif data_key == 'large':
                    for scan_path, _ in self.current_scan_data.get('large', []):
                        if scan_path == file_path:
                            files_to_delete.append(file_path)
                            break
                elif data_key == 'dup':
                    for hash_val, file_list in self.current_scan_data.get('dup', {}).items():
                        if file_path in file_list:
                            files_to_delete.append(file_path)
                            break
                elif data_key == 'dev':
                    for dev_data in self.current_scan_data.get('dev', []):
                        if len(dev_data) >= 4:  # 新格式包含content_analysis
                            dev_path = dev_data[0]
                        else:  # 兼容旧格式
                            dev_path = dev_data[0] if len(dev_data) > 0 else ''
                        if dev_path == file_path:
                            files_to_delete.append(file_path)
                            break
            
            for child in tree.get_children(item_id):
                if self.checked_items[tree_name].get(child, False):
                    collect_files(child)
        
        for item in checked_items:
            collect_files(item)
        
        files_to_delete = list(set(files_to_delete))
        
        if not files_to_delete:
            messagebox.showwarning("警告", "未找到可删除的文件！")
            return
        
        # 简化确认对话框，不计算详细大小（避免卡死）
        confirm_msg = f"确定要删除以下内容吗？\n\n" \
                     f"文件/目录数量: {len(files_to_delete)} 个\n\n" \
                     f"此操作不可撤销！"
        
        if messagebox.askyesno("删除确认", confirm_msg):
            self.add_log(f">> 开始删除 {len(files_to_delete)} 个选中的文件/目录...", 'info')
            
            # 使用异步删除，避免UI卡死
            self.start_async_delete(files_to_delete, tree, tree_name)
        else:
            self.add_log("[INFO] 用户取消删除操作", 'info')

    def start_async_delete(self, files_to_delete, tree, tree_name):
        """启动异步删除操作"""
        import threading
        
        # 禁用删除按钮，防止重复操作
        self.set_delete_button_state(False)
        
        # 更新状态
        self.update_status("正在删除文件，请稍候...")
        self.progress['value'] = 0
        
        def delete_worker():
            """删除工作线程"""
            try:
                # 计数器
                completed = 0
                total = len(files_to_delete)
                
                def progress_callback(message, level='info'):
                    nonlocal completed
                    completed += 1
                    progress = (completed / total) * 100
                    self.root.after(0, self.update_progress, progress)
                    self.root.after(0, self.add_log, message, level)
                
                # 执行删除
                success, error = self.core.delete_files(files_to_delete, progress_callback)
                
                # 在主线程中更新UI
                self.root.after(0, self.on_delete_completed, success, error, files_to_delete, tree, tree_name)
                
            except Exception as e:
                self.root.after(0, self.on_delete_error, str(e), tree, tree_name)
        
        # 启动删除线程
        delete_thread = threading.Thread(target=delete_worker, daemon=True)
        delete_thread.start()

    def on_delete_completed(self, success, error, files_to_delete, tree, tree_name):
        """删除完成后的处理"""
        # 重新启用删除按钮
        self.set_delete_button_state(True)
        
        # 更新状态
        self.update_status("删除操作完成")
        self.progress['value'] = 100
        
        # 显示结果
        if error == 0:
            result_msg = f"🎉 删除操作全部成功！\n\n✅ 成功删除: {success} 个文件/目录\n\n所有选中的项目已被成功删除。"
            messagebox.showinfo("删除成功", result_msg)
            self.add_log(f"[SUCCESS] ✅ 删除操作全部成功: {success} 个文件/目录", 'success')
        else:
            result_msg = f"⚠️ 删除操作部分完成\n\n✅ 成功删除: {success} 个\n❌ 删除失败: {error} 个\n\n请检查日志了解失败原因。"
            messagebox.showwarning("删除部分完成", result_msg)
            self.add_log(f"[WARNING] ⚠️ 删除操作部分完成: 成功 {success} 个, 失败 {error} 个", 'warning')
            
            # 智能更新UI：只删除实际被删除的文件节点
            deleted_count = 0
            
            def should_remove_item(item_id):
                """判断是否应该删除此UI项目"""
                item_data = tree.item(item_id)
                tags = item_data.get('tags', [])
                
                if not tags or len(tags) == 0:
                    return False
                    
                file_path = tags[0]
                
                # 如果是分组标签，不直接删除
                if file_path in ['duplicate_group', 'project_type_group', 'category_group']:
                    return False
                
                # 只有当文件路径在删除列表中时才删除
                return file_path in files_to_delete
            
            def remove_items_recursively(parent_id=''):
                """递归删除项目，但保留有子项目的分组"""
                children = list(tree.get_children(parent_id))
                
                for child_id in children:
                    # 先递归处理子项目
                    remove_items_recursively(child_id)
                    
                    # 判断是否删除当前项目
                    if should_remove_item(child_id):
                        try:
                            tree.delete(child_id)
                            nonlocal deleted_count
                            deleted_count += 1
                            # 从选中状态中移除
                            if child_id in self.checked_items[tree_name]:
                                del self.checked_items[tree_name][child_id]
                        except:
                            pass
                    else:
                        # 如果是分组节点，检查是否还有子项目
                        item_data = tree.item(child_id)
                        tags = item_data.get('tags', [])
                        if tags and len(tags) > 0:
                            file_path = tags[0]
                            if file_path in ['duplicate_group', 'project_type_group', 'category_group']:
                                # 如果分组下没有子项目了，删除分组
                                if not tree.get_children(child_id):
                                    try:
                                        tree.delete(child_id)
                                        deleted_count += 1
                                        if child_id in self.checked_items[tree_name]:
                                            del self.checked_items[tree_name][child_id]
                                    except:
                                        pass
            
            # 执行智能删除
            remove_items_recursively()
            
            self.add_log(f"[INFO] 📋 界面更新完成: 从列表中移除了 {deleted_count} 个项目", 'info')

    def on_delete_error(self, error_msg, tree, tree_name):
        """删除过程中发生错误的处理"""
        # 重新启用删除按钮
        self.set_delete_button_state(True)
        
        # 更新状态
        self.update_status("删除操作失败")
        
        # 显示错误
        messagebox.showerror("删除失败", f"删除过程中发生错误:\n\n{error_msg}")
        self.add_log(f"[ERROR] ❌ 删除操作失败: {error_msg}", 'error')

    def set_delete_button_state(self, enabled):
        """设置删除按钮状态"""
        try:
            if hasattr(self, 'delete_btn'):
                self.delete_btn['state'] = 'normal' if enabled else 'disabled'
        except:
            pass

    def update_progress(self, value):
        """更新进度条"""
        try:
            if hasattr(self, 'progress'):
                self.progress['value'] = value
                self.root.update_idletasks()
        except:
            pass

    def select_all(self):
        """全选当前标签页的所有项目"""
        current_tab = self.root.nametowidget(self.root.focus_get()).master
        
        if current_tab == self.temp_frame:
            tree = self.temp_tree
        elif current_tab == self.dup_frame:
            tree = self.dup_tree
        elif current_tab == self.large_frame:
            tree = self.large_tree
        elif current_tab == self.dev_frame:
            tree = self.dev_tree
        else:
            return
        
        self.toggle_all_selection(tree)

    def clear_selection(self):
        """清空当前标签页的选择"""
        current_tab = self.root.nametowidget(self.root.focus_get()).master
        
        if current_tab == self.temp_frame:
            tree = self.temp_tree
            tree_name = 'temp'
        elif current_tab == self.dup_frame:
            tree = self.dup_tree
            tree_name = 'dup'
        elif current_tab == self.large_frame:
            tree = self.large_tree
            tree_name = 'large'
        elif current_tab == self.dev_frame:
            tree = self.dev_tree
            tree_name = 'dev'
        else:
            return
        
        if tree_name in self.checked_items:
            self.checked_items[tree_name] = {}
        
        for item in tree.get_children():
            tree.set(item, 'check', '☐')
            for child in tree.get_children(item):
                tree.set(child, 'check', '☐')
        
        tree.heading('check', text='☐')